package com.hcl.orm.core.dialect.handler.page;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.hcl.orm.core.annotation.DBType;
import com.hcl.orm.core.dialect.SqlDefinition;
import com.hcl.orm.core.dialect.SqlMetadata;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author hucl
 * @projectName hcl-orm
 * @description: Oracle分页翻译
 * @date 2021/8/1116:33
 */
@Component
public class OracleQueryPageDialectHandler extends QueryPageDialectHandler {
    private static final String SIMPLE_PAGE_QUERY_TMPL = "select * from ("
            + "select rownum as row_no, a.* from "
            + "{} a) where row_no >? and row_no<=?;";

    public OracleQueryPageDialectHandler() {
        super("Oracle SQL分页方言处理器");
    }

    @Override
    protected void doHandle(SqlDefinition sqlDefinition) {
        final SqlMetadata metadata = sqlDefinition.getSelectedSqlMetadata();

        if (!StrUtil.isEmpty(metadata.getRawSql())) {
            sqlDefinition.setPageQueryCountSql(StrUtil.replace(sqlDefinition.getDialectSql().toLowerCase(),
                    FIELDS_PATTERN, m -> " count(*) "));
            String queryPageTmpl = "select * from ({})  where row_no >? and row_no<=?";
            sqlDefinition.setDialectSql(StrUtil.format(queryPageTmpl, StrUtil.replace(sqlDefinition.getDialectSql().toLowerCase(),
                    FIELDS_PATTERN, m -> " rownum as row_no," + m.group())));
        } else {
            String tableName = metadata.getTableName();
            sqlDefinition.setPageQueryCountSql(StrUtil.format(SIMPLE_PAGE_QUERY_COUT_TMPL, tableName));
            sqlDefinition.setDialectSql(StrUtil.format(SIMPLE_PAGE_QUERY_TMPL, tableName));
        }

        sqlDefinition.setPageParamFunction(pageParam -> new Object[]{pageParam.getPageSize() * (pageParam.getPageNo() - 1),
                pageParam.getPageSize() * pageParam.getPageNo()});
    }

    @Override
    protected List<DBType> getTargetDB() {
        return ListUtil.toList(DBType.ORACLE,DBType.OB_ORC);
    }
}
